package com.ksyun.campus.metaserver.controller;

import cn.hutool.core.util.ObjectUtil;
import com.ksyun.campus.metaserver.common.result.BaseResult;
import com.ksyun.campus.metaserver.entity.dto.req.WriteReqDto;
import com.ksyun.campus.metaserver.entity.meta.StatInfo;
import com.ksyun.campus.metaserver.entity.meta.tree.FileTreeManager;
import com.ksyun.campus.metaserver.service.MetaService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/meta")
@RequiredArgsConstructor
public class MetaController {

    private final MetaService metaService;
    private final ConfigurableApplicationContext applicationContext;

    /**
     * 根据path获取文件的元数据
     *
     * @param fileSystemName 命名空间
     * @param path           文件路径
     * @return 文件元数据
     */
    @RequestMapping("/stats")
    public BaseResult<StatInfo> stats(
            @RequestHeader String fileSystemName,
            @RequestParam String path
    ) {
        return metaService.getStats(fileSystemName, path);
    }

    /**
     * 创建文件
     *
     * @param fileSystemName 命名空间
     * @param path           文件路径
     * @return 文件元数据
     */
    @RequestMapping("/create")
    public BaseResult<StatInfo> createFile(
            @RequestHeader String fileSystemName,
            @RequestParam String path
    ) {
        if (!path.contains(".")) {
            throw new RuntimeException(String.format("路径不是文件，请检查路径 [path]: %s", path));
        }
        return metaService.createFile(fileSystemName, path);
    }

    /**
     * 创建文件夹
     *
     * @param fileSystemName 命名空间
     * @param path           文件路径
     * @return 文件夹元数据
     */
    @RequestMapping("/mkdir")
    public BaseResult<StatInfo> mkdir(
            @RequestHeader String fileSystemName,
            @RequestParam String path
    ) {
        if (path.contains(".")) {
            throw new RuntimeException(String.format("路径不是文件夹，请检查路径 [path]: %s", path));
        }
        return metaService.mkdir(fileSystemName, path);
    }

    /**
     * 查询当前路径下的所有文件夹和文件夹的路径
     *
     * @param fileSystemName 命名空间
     * @param path           文件路径
     * @return 当前path下的文件夹列表
     */
    @RequestMapping("/listdir")
    public BaseResult<List<String>> listdir(
            @RequestHeader String fileSystemName,
            @RequestParam String path
    ) {
        return metaService.listdir(fileSystemName, path);
    }

    /**
     * 删除文件
     *
     * @param fileSystemName 命名空间
     * @param path           文件路径
     */
    @RequestMapping("/delete")
    public BaseResult<StatInfo> delete(
            @RequestHeader String fileSystemName,
            @RequestParam String path
    ) {
        return metaService.delete(fileSystemName, path);
    }

    /**
     * 保存文件写入成功后的元数据信息，包括文件path、size、三副本信息等
     *
     * @param fileSystemName 命名空间
     * @param writeReqDto    写文件请求实体
     */
    @RequestMapping("/write")
    public BaseResult<String> commitWrite(
            @RequestHeader String fileSystemName,
            @RequestBody WriteReqDto writeReqDto
    ) {
        return metaService.commitWrite(fileSystemName, writeReqDto);
    }

    /**
     * 删除失败回调恢复接口
     * @param fileSystemName 命名空间
     */
    @RequestMapping("/deleteError")
    public BaseResult<String> deleteErrorRecovery(
            @RequestHeader String fileSystemName,
            @RequestBody StatInfo statInfo
    ) {
        if (ObjectUtil.isNotNull(statInfo)) {
            return metaService.deleteErrorRecovery(fileSystemName, statInfo);
        } else {
            throw new RuntimeException("删除错误回调接口接受请求参数为null");
        }
    }

    /**
     * 根据文件path查询三副本的位置，返回客户端具体ds、文件分块信息
     *
     * @param fileSystemName 命名空间
     * @param path           文件路径
     * @return 文件元数据
     */
    @RequestMapping("/open")
    public BaseResult<StatInfo> open(
            @RequestHeader String fileSystemName,
            @RequestParam String path
    ) {
        if (!path.contains(".")) {
            throw new RuntimeException(String.format("路径不是文件，请检查路径 [path]: %s", path));
        }
        return metaService.open(fileSystemName, path);
    }

    /**
     * 关闭退出进程
     */
    @RequestMapping("/shutdown")
    public void shutdownServer() {
        applicationContext.close();
    }

    // 附加方法

    /**
     * 获取当前路径下的所有文件元数据信息
     *
     * @param fileSystemName 命名空间
     * @param path           目录路径
     * @return 文件元数据信息集合
     */
    @RequestMapping("/listFileStats")
    public BaseResult<List<StatInfo>> listFileStats(
            @RequestHeader String fileSystemName,
            @RequestParam String path
    ) {
        return metaService.listFileStats(fileSystemName, path);
    }
}
